package com.javabi.htmlbuilder.css;

import java.util.Collection;
import java.util.HashSet;

import com.javabi.htmlbuilder.HTMLColor;
import com.javabi.htmlbuilder.css.border.Border;
import com.javabi.htmlbuilder.css.border.BorderStyle;
import com.javabi.htmlbuilder.css.declaration.CSSColor;
import com.javabi.htmlbuilder.css.declaration.Height;
import com.javabi.htmlbuilder.css.declaration.TextDecoration;
import com.javabi.htmlbuilder.css.declaration.Width;
import com.javabi.htmlbuilder.css.font.FontFamily;
import com.javabi.htmlbuilder.css.font.FontSize;
import com.javabi.htmlbuilder.css.font.FontStyle;
import com.javabi.htmlbuilder.css.font.FontWeight;
import com.javabi.htmlbuilder.css.margin.Margin;
import com.javabi.htmlbuilder.css.margin.MarginBottom;
import com.javabi.htmlbuilder.css.margin.MarginLeft;
import com.javabi.htmlbuilder.css.margin.MarginRight;
import com.javabi.htmlbuilder.css.margin.MarginTop;
import com.javabi.htmlbuilder.css.padding.Padding;
import com.javabi.htmlbuilder.css.padding.PaddingBottom;
import com.javabi.htmlbuilder.css.padding.PaddingLeft;
import com.javabi.htmlbuilder.css.padding.PaddingRight;
import com.javabi.htmlbuilder.css.padding.PaddingTop;
import com.javabi.htmlbuilder.css.unit.CSSUnit;
import com.javabi.htmlbuilder.css.unit.Pixels;

/**
 * A CSS Declaration Set
 */
public class CSSDeclarationSet extends HashSet<CSSDeclaration> implements CSSElement {

	/** The serialization ID. */
	private static final long serialVersionUID = -6183901152234523919L;

	@Override
	public boolean add(CSSDeclaration declaration) {
		if (declaration == null) {
			throw new NullPointerException();
		}
		return super.add(declaration);
	}

	/**
	 * Append a font family declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet fontSize(int pixels) {
		FontSize declaration = new FontSize(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a margin left declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet marginLeft(int pixels) {
		MarginLeft declaration = new MarginLeft(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a margin right declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet marginRight(int pixels) {
		MarginRight declaration = new MarginRight(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a margin top declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet marginTop(int pixels) {
		MarginTop declaration = new MarginTop(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a margin bottom declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet marginBottom(int pixels) {
		MarginBottom declaration = new MarginBottom(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a padding left declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet paddingLeft(int pixels) {
		PaddingLeft declaration = new PaddingLeft(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a padding right declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet paddingRight(int pixels) {
		PaddingRight declaration = new PaddingRight(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a padding top declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet paddingTop(int pixels) {
		PaddingTop declaration = new PaddingTop(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a padding bottom declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet paddingBottom(int pixels) {
		PaddingBottom declaration = new PaddingBottom(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a width declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet width(int pixels) {
		Width declaration = new Width(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a height declaration.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet height(int pixels) {
		Height declaration = new Height(new Pixels(pixels));
		add(declaration);
		return this;
	}

	/**
	 * Append a italic font style.
	 * @return this set.
	 */
	public CSSDeclarationSet italic() {
		add(FontStyle.ITALIC);
		return this;
	}

	/**
	 * Append a bold font weight.
	 * @return this set.
	 */
	public CSSDeclarationSet bold() {
		add(FontWeight.BOLD);
		return this;
	}

	/**
	 * Append an underline text decoration.
	 * @return this set.
	 */
	public CSSDeclarationSet underline() {
		add(TextDecoration.UNDERLINE);
		return this;
	}

	/**
	 * Append an line through text decoration.
	 * @return this set.
	 */
	public CSSDeclarationSet lineThrough() {
		add(TextDecoration.LINE_THROUGH);
		return this;
	}

	/**
	 * Append a font family declaration.
	 * @param fontName the font name.
	 * @return this set.
	 */
	public CSSDeclarationSet fontFamily(String fontName) {
		FontFamily declaration = new FontFamily(fontName);
		add(declaration);
		return this;
	}

	/**
	 * Append a font family declaration.
	 * @param fontNames the font names.
	 * @return this set.
	 */
	public CSSDeclarationSet fontFamily(String... fontNames) {
		FontFamily declaration = new FontFamily(fontNames);
		add(declaration);
		return this;
	}

	/**
	 * Append a font family declaration.
	 * @param fontNames the font names.
	 * @return this set.
	 */
	public CSSDeclarationSet fontFamily(Collection<String> fontNames) {
		FontFamily declaration = new FontFamily(fontNames);
		add(declaration);
		return this;
	}

	/**
	 * Append a color.
	 * @param color the color.
	 * @return this set.
	 */
	public CSSDeclarationSet color(CSSColor color) {
		add(color);
		return this;
	}

	/**
	 * Append a color.
	 * @param color the color.
	 * @return this set.
	 */
	public CSSDeclarationSet color(HTMLColor color) {
		return color(new CSSColor(CSSPropertyName.COLOR, color));
	}

	/**
	 * Append a background color.
	 * @param color the background color.
	 * @return this set.
	 */
	public CSSDeclarationSet backgroundColor(HTMLColor color) {
		return color(new CSSColor(CSSPropertyName.BACKGROUND_COLOR, color));
	}

	/**
	 * Append a border color.
	 * @param color the border color.
	 * @return this set.
	 */
	public CSSDeclarationSet borderColor(HTMLColor color) {
		return color(new CSSColor(CSSPropertyName.BORDER_COLOR, color));
	}

	/**
	 * Append a border left color.
	 * @param color the border left color.
	 * @return this set.
	 */
	public CSSDeclarationSet borderLeftColor(HTMLColor color) {
		return color(new CSSColor(CSSPropertyName.BORDER_LEFT_COLOR, color));
	}

	/**
	 * Append a border right color.
	 * @param color the border right color.
	 * @return this set.
	 */
	public CSSDeclarationSet borderRightColor(HTMLColor color) {
		return color(new CSSColor(CSSPropertyName.BORDER_RIGHT_COLOR, color));
	}

	/**
	 * Append a border top color.
	 * @param color the border top color.
	 * @return this set.
	 */
	public CSSDeclarationSet borderTopColor(HTMLColor color) {
		return color(new CSSColor(CSSPropertyName.BORDER_TOP_COLOR, color));
	}

	/**
	 * Append a border bottom color.
	 * @param color the border bottom color.
	 * @return this set.
	 */
	public CSSDeclarationSet borderBottomColor(HTMLColor color) {
		return color(new CSSColor(CSSPropertyName.BORDER_BOTTOM_COLOR, color));
	}

	/**
	 * Append a solid border.
	 * @param width the width in pixels.
	 * @param color the color.
	 * @return this set.
	 */
	public CSSDeclarationSet border(int width, HTMLColor color) {
		Border declaration = new Border(new Pixels(width), BorderStyle.SOLID, color);
		add(declaration);
		return this;
	}

	/**
	 * Append a margin in pixels.
	 * @param top the top margin.
	 * @param right the right margin.
	 * @param bottom the bottom margin.
	 * @param left the left margin.
	 * @return this set.
	 */
	public CSSDeclarationSet margin(int top, int right, int bottom, int left) {
		Margin declaration = new Margin(CSSUnit.PIXELS, top, right, bottom, left);
		add(declaration);
		return this;
	}

	/**
	 * Append a margin in pixels.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet margin(int pixels) {
		return margin(pixels, pixels, pixels, pixels);
	}

	/**
	 * Append a padding in pixels.
	 * @param top the top padding.
	 * @param right the right padding.
	 * @param bottom the bottom padding.
	 * @param left the left padding.
	 * @return this set.
	 */
	public CSSDeclarationSet padding(int top, int right, int bottom, int left) {
		Padding declaration = new Padding(CSSUnit.PIXELS, top, right, bottom, left);
		add(declaration);
		return this;
	}

	/**
	 * Append a padding in pixels.
	 * @param pixels the pixels.
	 * @return this set.
	 */
	public CSSDeclarationSet padding(int pixels) {
		return padding(pixels, pixels, pixels, pixels);
	}

	/**
	 * Append this to the given css builder.
	 * @param css the css builder.
	 * @return the css builder.
	 */
	public CSSBuilder appendTo(CSSBuilder css) {
		css.declarations(this, false);
		return css;
	}

	@Override
	public String toString() {
		CSSBuilder css = new CSSBuilder();
		appendTo(css);
		return css.toString();
	}

}
